package com.mtons.mblog.modules.service.impl;

import com.mtons.mblog.base.lang.Consts;
import com.mtons.mblog.modules.repository.ChannelRepository;
import com.mtons.mblog.modules.service.ChannelService;
import com.mtons.mblog.modules.data.ChannelVO;
import com.mtons.mblog.modules.entity.Channel;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional(readOnly = true)
public class ChannelServiceImpl implements ChannelService {
	@Autowired
	private ChannelRepository channelRepository;

	@Override
	public List<Channel> findAll(int status) {
		Sort sort = Sort.by(Sort.Direction.DESC, "weight", "id");
		List<Channel> list;
		if (status > Consts.IGNORE) {
			list = channelRepository.findAllByStatus(status, sort);
		} else {
			list = channelRepository.findAll(sort);
		}
		return list;
	}
	
	@Override
	public List<ChannelVO> findAllLoop(int status) {
		Sort sort = Sort.by(Sort.Direction.DESC, "weight", "id");
		List<Channel> list;
		if (status > Consts.IGNORE) {
			list = channelRepository.findAllByStatus(status, sort);
		} else {
			list = channelRepository.findAll(sort);
		}
		List<ChannelVO> vos = new ArrayList<ChannelVO>();
		list.forEach(c -> {
			ChannelVO vo = new ChannelVO();
			BeanUtils.copyProperties(c, vo);
			vos.add(vo);
		});
		List<ChannelVO> returnList = getChild(null, vos);
		return returnList;
	}
	
	private List<ChannelVO> getChild(Integer id, List<ChannelVO> root) {
	    // 子菜单
	    List<ChannelVO> pList = root.stream().filter(c -> c.getParentId() == id).collect(Collectors.toList());
	    // 把子菜单的子菜单再循环一遍
	    pList.forEach(p -> {
	    	p.setList(getChild(p.getId(), root));
	    });
	    if (pList.size() == 0) {
	        return null;
	    }
	    return pList;
	}

	@Override
	public Map<Integer, Channel> findMapByIds(Collection<Integer> ids) {
		List<Channel> list = channelRepository.findAllById(ids);
		if (null == list) {
			return Collections.emptyMap();
		}
		return list.stream().collect(Collectors.toMap(Channel::getId, n -> n));
	}

	@Override
	public Channel getById(int id) {
		return channelRepository.findById(id).get();
	}

	@Override
	@Transactional
	public void update(Channel channel) {
		Optional<Channel> optional = channelRepository.findById(channel.getId());
		Channel po = optional.orElse(new Channel());
		BeanUtils.copyProperties(channel, po);
		if(StringUtils.isNoneBlank(po.getLogo()) && !po.getLogo().endsWith("fa-fw")) {
			po.setLogo(po.getLogo() + " fa-fw");
		}
		channelRepository.save(po);
	}

	@Override
	@Transactional
	public void updateWeight(Integer id, Integer parentId) {
		Channel po = channelRepository.findById(id).get();

		int max = Consts.ZERO;
		if(parentId == null) {
			max = channelRepository.maxWeight() + 1;
		}else {
			max = channelRepository.maxWeight(parentId) + 1;
		}
		
		po.setWeight(max);
		channelRepository.save(po);
	}

	@Override
	@Transactional
	public void delete(int id) {
		channelRepository.deleteById(id);
	}

	@Override
	public long count() {
		return channelRepository.count();
	}

	@Override
	public ChannelVO findChild(int channelId) {
		Optional<Channel> o = channelRepository.findById(channelId);
		if(!o.isPresent()) {
			return null;
		}
		Sort sort = Sort.by(Sort.Direction.DESC, "weight", "id");
		List<Channel> list = channelRepository.findAllByStatusAndParentId(0, sort, channelId);
		ChannelVO vo = new ChannelVO();
		BeanUtils.copyProperties(o.get(), vo);
		List<ChannelVO> vos = new ArrayList<ChannelVO>();
		if(list.size() > 0) {
			list.forEach(c -> {
				ChannelVO cvo = new ChannelVO();
				BeanUtils.copyProperties(c, cvo);
				vos.add(cvo);
			});
		}
		vo.setList(vos);
		return vo;
	}

}
